
// ================================================================================================
// -*- C++ -*-
// File: MapCell.hpp
// Author: Guilherme R. Lampert
// Created on: 16/09/13
// Brief: Representation of a single cell in the game map.
// ================================================================================================

#ifndef __MAPCELL_HPP__
#define __MAPCELL_HPP__

// Define portable sized integer types.
// 'stdint.h' is not available on some versions of Visual Studio.
#ifdef _MSC_VER
	typedef __int16 INT_16;
	typedef __int32 INT_32;
	typedef __int64 INT_64;
#else // !_MSC_VER
	#include <stdint.h>
	typedef int16_t INT_16;
	typedef int32_t INT_32;
	typedef int64_t INT_64;
#endif // _MSC_VER

// Safe to assume 'unsigned char' is one byte wide
// pretty much everywhere. Can hold a value from 0 to 255.
typedef unsigned char BYTE_8;

// Locations in the map can be accessed
// by its x and y coordinate or its 'row' and 'column' aliases
// or even the array index 0 and 1 of field alias 'data'.
union Location {

	INT_32 data[2];
	struct {
		INT_32 x;
		INT_32 y;
	};
	struct {
		INT_32 row;
		INT_32 col;
	};
};

// Cell contents:
enum MapCellContents {

	CC_WATER    = 1,
	CC_FOOD     = 2,
	CC_ANT      = 3,
	CC_DEAD_ANT = 4,
	CC_ANT_HILL = 5
};

// Map cell. Should be as slim as possible
// to save memory when used with big maps.
struct MapCell {

	// Player number, if contents == ant or hill:
	INT_16 player;   // -> 2 bytes

	// What is in this cell (food/water/ant/etc):
	BYTE_8 contents; // -> 1 byte

	// Visible or unknown:
	BYTE_8 visible;  // -> 1 byte
};

// Sets all fields to invalid values
inline void CellClear(MapCell & cell)
{
	cell.player   = -1;
	cell.contents = 0;
	cell.visible  = 0;
}

// Handy macros:
#define CellSetPlayer(cell, p)   (cell).player = (INT_16)(p)
#define CellSetContents(cell, c) (cell).contents = (BYTE_8)(c)
#define CellSetVisible(cell)     (cell).visible = 1
#define CellSetUnknown(cell)     (cell).visible = 0
#define CellIsWater(cell)        ((cell).contents == CC_WATER)
#define CellIsFood(cell)         ((cell).contents == CC_FOOD)
#define CellIsAnt(cell)          ((cell).contents == CC_ANT)
#define CellIsDeadAnt(cell)      ((cell).contents == CC_DEAD_ANT)
#define CellIsAntHill(cell)      ((cell).contents == CC_ANT_HILL)
#define CellIsVisible(cell)      ((cell).visible == 1)
#define CellIsUnknown(cell)      ((cell).visible == 0)

#endif // __MAPCELL_HPP__
